package com.yuanqi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuanqi.entity.Inventory;
import com.yuanqi.entity.InventoryTxn;
import com.yuanqi.entity.WareGrn;
import com.yuanqi.entity.WareGrnItem;
import com.yuanqi.mapper.InventoryMapper;
import com.yuanqi.mapper.InventoryTxnMapper;
import com.yuanqi.mapper.WareGrnItemMapper;
import com.yuanqi.service.InventoryService;
import com.yuanqi.service.WareGrnItemService;
import com.yuanqi.service.WareGrnService;
import com.yuanqi.mapper.WareGrnMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.*;
import java.util.Calendar;

/**
* @author HP
* @description 针对表【ware_grn(入库单)】的数据库操作Service实现
* @createDate 2025-08-26 14:58:48
*/
@Slf4j
@Service
public class WareGrnServiceImpl extends ServiceImpl<WareGrnMapper, WareGrn>
    implements WareGrnService{

    @Autowired
    private WareGrnItemMapper wareGrnItemMapper;
    
    @Autowired
    private WareGrnItemService wareGrnItemService;
    
    @Autowired
    private InventoryService inventoryService;
    
    @Autowired
    private InventoryMapper inventoryMapper;
    
    @Autowired
    private InventoryTxnMapper inventoryTxnMapper;
    
    @Autowired
    private com.yuanqi.mapper.SkuMapper skuMapper;
    
    @Autowired
    private com.yuanqi.mapper.ProductMapper productMapper;

    @Override
    public IPage<WareGrn> listGrns(Integer page, Integer size, String grnCode, Long warehouseId, Integer status) {
        Page<WareGrn> pageParam = new Page<>(page, size);
        LambdaQueryWrapper<WareGrn> queryWrapper = new LambdaQueryWrapper<>();
        
        if (StringUtils.hasText(grnCode)) {
            queryWrapper.like(WareGrn::getGrnCode, grnCode);
        }
        
        if (warehouseId != null) {
            queryWrapper.eq(WareGrn::getWarehouseId, warehouseId);
        }
        
        if (status != null) {
            queryWrapper.eq(WareGrn::getStatus, status);
        }
        
        queryWrapper.orderByDesc(WareGrn::getCreatedAt);
        
        return this.page(pageParam, queryWrapper);
    }

    @Override
    public Map<String, Object> getGrnDetail(Long id) {
        // 获取入库单主表信息
        WareGrn grn = this.getById(id);
        if (grn == null) {
            return null;
        }
        
        // 获取入库单明细
        LambdaQueryWrapper<WareGrnItem> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WareGrnItem::getGrnId, id);
        List<WareGrnItem> items = wareGrnItemMapper.selectList(queryWrapper);
        
        Map<String, Object> result = new HashMap<>();
        result.put("grn", grn);
        result.put("items", items);
        
        return result;
    }

    @Override
    @Transactional
    public boolean createGrn(WareGrn grn, List<Map<String, Object>> itemsData) {
        try {
            // 生成入库单号
            if (!StringUtils.hasText(grn.getGrnCode())) {
                grn.setGrnCode("GRN" + System.currentTimeMillis());
            }
            
            // 设置初始状态为新建
            grn.setStatus(0);
            grn.setCreatedAt(new Date());
            
            // 保存入库单主表
            boolean saved = this.save(grn);
            if (!saved) {
                throw new RuntimeException("保存入库单主表失败");
            }
        
        // 保存入库单明细
        List<WareGrnItem> items = new ArrayList<>();
        for (Map<String, Object> itemData : itemsData) {
            WareGrnItem item = new WareGrnItem();
            item.setGrnId(grn.getId());
            
            // 设置明细数据
            if (itemData.containsKey("poItemId") && itemData.get("poItemId") != null && !itemData.get("poItemId").toString().isEmpty()) {
                item.setPoItemId(Long.valueOf(itemData.get("poItemId").toString()));
            }
            
            if (itemData.containsKey("locationId") && itemData.get("locationId") != null && !itemData.get("locationId").toString().isEmpty()) {
                item.setLocationId(Long.valueOf(itemData.get("locationId").toString()));
            } else {
                // 设置默认库位ID为1（需要确保数据库中有id=1的库位记录）
                item.setLocationId(1L);
            }
            
            if (itemData.containsKey("skuId")) {
                item.setSkuId(Long.valueOf(itemData.get("skuId").toString()));
            }
            
            if (itemData.containsKey("batchNo")) {
                item.setBatchNo(itemData.get("batchNo").toString());
            }
            
            if (itemData.containsKey("expiryDate") && itemData.get("expiryDate") != null) {
                try {
                    // 处理日期格式转换
                    String dateStr = itemData.get("expiryDate").toString();
                    if (!dateStr.isEmpty()) {
                        item.setExpiryDate(java.sql.Date.valueOf(dateStr));
                    }
                } catch (Exception e) {
                    // 日期格式错误时设为null
                    item.setExpiryDate(null);
                }
            }
            
            if (itemData.containsKey("qty") && itemData.get("qty") != null) {
                item.setQty(new java.math.BigDecimal(itemData.get("qty").toString()));
            } else {
                // 如果没有提供数量，设置默认值为1
                item.setQty(new java.math.BigDecimal("1"));
            }
            
            if (itemData.containsKey("price") && itemData.get("price") != null) {
                item.setPrice(new java.math.BigDecimal(itemData.get("price").toString()));
            } else {
                // 如果没有提供价格，设置默认值为0
                item.setPrice(new java.math.BigDecimal("0"));
            }
            
            items.add(item);
            }
            
            return wareGrnItemService.saveBatch(items);
        } catch (Exception e) {
            throw new RuntimeException("创建入库单失败: " + e.getMessage(), e);
        }
    }

    @Override
    @Transactional
    public boolean submitGrn(Long id) {
        WareGrn grn = this.getById(id);
        if (grn == null || (grn.getStatus() != 0 && grn.getStatus() != 4)) {
            return false;
        }
        
        // 如果是驳回状态，检查是否已修改
        if (grn.getStatus() == 4) {
            // 检查是否有修改记录（通过比较更新时间）
            // 这里可以通过检查明细表是否有更新记录来判断
            // 或者添加一个修改标记字段
            // 暂时允许提交，但可以在前端进行控制
        }
        
        // 更新状态为待审核
        grn.setStatus(1);
        return this.updateById(grn);
    }

    @Override
    @Transactional
    public boolean approveGrn(Long id) {
        WareGrn grn = this.getById(id);
        if (grn == null || grn.getStatus() != 1) {
            return false;
        }
        
        // 更新状态为已审核
        grn.setStatus(2);
        return this.updateById(grn);
    }

    @Override
    @Transactional
    public boolean rejectGrn(Long id) {
        WareGrn grn = this.getById(id);
        if (grn == null || grn.getStatus() != 1) {
            return false;
        }
        
        // 更新状态为已驳回
        grn.setStatus(4);
        return this.updateById(grn);
    }

    @Override
    @Transactional
    public boolean updateGrn(WareGrn grn, List<Map<String, Object>> itemsData) {
        // 检查入库单是否存在且状态允许修改
        WareGrn existingGrn = this.getById(grn.getId());
        if (existingGrn == null || existingGrn.getStatus() != 4) {
            return false; // 只有驳回状态的入库单才能修改
        }

        // 更新入库单基本信息
        boolean updateResult = this.updateById(grn);
        if (!updateResult) {
            return false;
        }

        // 删除原有的入库单明细
        LambdaQueryWrapper<WareGrnItem> deleteWrapper = new LambdaQueryWrapper<>();
        deleteWrapper.eq(WareGrnItem::getGrnId, grn.getId());
        wareGrnItemMapper.delete(deleteWrapper);

        // 添加新的入库单明细
        for (Map<String, Object> itemData : itemsData) {
            WareGrnItem item = new WareGrnItem();
            item.setGrnId(grn.getId());
            item.setSkuId(Long.valueOf(itemData.get("skuId").toString()));
            item.setQty(new BigDecimal(itemData.get("qty").toString()));
            
            // 设置单价（使用price字段）
            if (itemData.containsKey("price") && itemData.get("price") != null) {
                item.setPrice(new BigDecimal(itemData.get("price").toString()));
            }
            
            // 设置默认库位（可以根据业务需求调整）
            item.setLocationId(1L); // 默认库位ID，实际应该根据业务逻辑设置
            
            wareGrnItemMapper.insert(item);
        }

        return true;
    }

    @Override
    @Transactional
    public boolean executeGrn(Long id) {
        WareGrn grn = this.getById(id);
        if (grn == null || grn.getStatus() != 2) {
            return false;
        }

        // 获取入库单明细
        LambdaQueryWrapper<WareGrnItem> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WareGrnItem::getGrnId, id);
        List<WareGrnItem> items = wareGrnItemMapper.selectList(queryWrapper);

        // 更新库存和创建库存事务
        for (WareGrnItem item : items) {
            // 查询是否已有该商品库存
            // 注意：唯一约束是 (warehouse_id, location_id, sku_id)，不包含批次号
            LambdaQueryWrapper<Inventory> inventoryQuery = new LambdaQueryWrapper<>();
            inventoryQuery.eq(Inventory::getSkuId, item.getSkuId())
                    .eq(Inventory::getWarehouseId, grn.getWarehouseId())
                    .eq(Inventory::getLocationId, item.getLocationId());

            Inventory inventory = inventoryMapper.selectOne(inventoryQuery);

            if (inventory == null) {
                // 创建新库存记录
                inventory = new Inventory();
                inventory.setSkuId(item.getSkuId());
                inventory.setWarehouseId(grn.getWarehouseId());
                inventory.setLocationId(item.getLocationId());
                inventory.setBatchNo(item.getBatchNo());
                inventory.setExpiryDate(item.getExpiryDate());

                // 新增库存：on_hand = available = 入库数量
                inventory.setOnHandQty(item.getQty());
                inventory.setAvailableQty(item.getQty());
                inventory.setOccupiedQty(BigDecimal.ZERO);

                inventory.setUpdatedAt(new Date());

                try {
                    inventoryMapper.insert(inventory);
                } catch (Exception e) {
                    // 如果插入失败（可能是并发插入），重新查询并更新
                    log.warn("插入库存记录失败，尝试重新查询: {}", e.getMessage());
                    inventory = inventoryMapper.selectOne(inventoryQuery);
                    if (inventory != null) {
                        // 更新现有库存
                        inventory.setOnHandQty(inventory.getOnHandQty().add(item.getQty()));
                        inventory.setAvailableQty(inventory.getAvailableQty().add(item.getQty()));
                        inventory.setUpdatedAt(new Date());
                        inventoryMapper.updateById(inventory);
                    } else {
                        throw new RuntimeException("库存记录创建失败: " + e.getMessage(), e);
                    }
                }
            } else {
                // 更新现有库存
                inventory.setOnHandQty(inventory.getOnHandQty().add(item.getQty()));
                inventory.setAvailableQty(inventory.getAvailableQty().add(item.getQty()));
                // occupied_qty 不变（入库不影响已占用数量）
                inventory.setUpdatedAt(new Date());

                inventoryMapper.updateById(inventory);
            }


            // 创建库存事务记录
            InventoryTxn txn = new InventoryTxn();
            txn.setWarehouseId(grn.getWarehouseId());
            txn.setLocationId(item.getLocationId());
            txn.setSkuId(item.getSkuId());
            txn.setBatchNo(item.getBatchNo());
            txn.setQty(item.getQty());

            // 如果有单价，可以传入；没有的话置为0
            txn.setUnitCost(item.getPrice() != null ? item.getPrice() : BigDecimal.ZERO);

            // 事务类型：入库
            txn.setTxnType("IN");

            // 参考单据（这里是 GRN 入库单）
            txn.setReferenceTable("ware_grn");
            txn.setReferenceId(grn.getId());

            // 可以拼接一个 remark 作为说明
            txn.setRemark("入库单执行: " + grn.getGrnCode());

            // 生成事务编码（比如用时间戳/UUID）
            txn.setTxnCode("TXN" + System.currentTimeMillis());

            inventoryTxnMapper.insert(txn);

        }

        // 更新入库单状态为已入库
        grn.setStatus(3);
        grn.setReceivedAt(new Date());

        return this.updateById(grn);
    }


    @Override
    public List<Map<String, Object>> getGrnRecords(String grnCode, String productName, Long warehouseId, Long skuId, String startDate, String endDate) {
        // 查询入库单明细
        LambdaQueryWrapper<WareGrnItem> itemQueryWrapper = new LambdaQueryWrapper<>();
        itemQueryWrapper.eq(skuId != null, WareGrnItem::getSkuId, skuId);
        
        List<WareGrnItem> items = wareGrnItemMapper.selectList(itemQueryWrapper);
        
        List<Map<String, Object>> records = new ArrayList<>();
        for (WareGrnItem item : items) {
            WareGrn grn = this.getById(item.getGrnId());
            if (grn == null) {
                continue;
            }
            
            // 应用过滤条件
            boolean shouldInclude = true;
            
            // 入库单号过滤
            if (StringUtils.hasText(grnCode) && !grn.getGrnCode().contains(grnCode)) {
                shouldInclude = false;
            }
            
            // 仓库过滤
            if (warehouseId != null && !warehouseId.equals(grn.getWarehouseId())) {
                shouldInclude = false;
            }
            
            // 日期过滤
            if (StringUtils.hasText(startDate) && grn.getCreatedAt() != null) {
                try {
                    Date start = java.sql.Date.valueOf(startDate);
                    if (grn.getCreatedAt().before(start)) {
                        shouldInclude = false;
                    }
                } catch (Exception ignored) {}
            }
            
            if (StringUtils.hasText(endDate) && grn.getCreatedAt() != null) {
                try {
                    Date end = java.sql.Date.valueOf(endDate);
                    Calendar cal = Calendar.getInstance();
                    cal.setTime(end);
                    cal.add(Calendar.DAY_OF_MONTH, 1); // 包含结束日期当天
                    if (grn.getCreatedAt().after(cal.getTime())) {
                        shouldInclude = false;
                    }
                } catch (Exception ignored) {}
            }
            
            // 商品名称过滤
            if (StringUtils.hasText(productName)) {
                try {
                    com.yuanqi.entity.Sku sku = skuMapper.selectById(item.getSkuId());
                    if (sku != null) {
                        com.yuanqi.entity.Product product = productMapper.selectById(sku.getProductId());
                        if (product == null || !product.getProductName().contains(productName)) {
                            shouldInclude = false;
                        }
                    } else {
                        shouldInclude = false;
                    }
                } catch (Exception e) {
                    shouldInclude = false;
                }
            }
            
            if (!shouldInclude) {
                continue;
            }
            
            Map<String, Object> record = new HashMap<>();
            record.put("id", item.getId());
            record.put("grnId", grn.getId());
            record.put("grnCode", grn.getGrnCode());
            record.put("skuId", item.getSkuId());
            record.put("qty", item.getQty());
            record.put("price", item.getPrice());
            record.put("batchNo", item.getBatchNo());
            record.put("locationId", item.getLocationId());
            record.put("warehouseId", grn.getWarehouseId());
            record.put("status", grn.getStatus());
            record.put("receivedAt", grn.getReceivedAt());
            record.put("createdAt", grn.getCreatedAt());
            
            // 添加商品信息
            try {
                com.yuanqi.entity.Sku sku = skuMapper.selectById(item.getSkuId());
                if (sku != null) {
                    record.put("skuCode", sku.getSkuCode());
                    com.yuanqi.entity.Product product = productMapper.selectById(sku.getProductId());
                    if (product != null) {
                        record.put("productName", product.getProductName());
                        record.put("productCode", product.getSpuCode());
                    }
                }
            } catch (Exception ignored) {
                record.put("skuCode", "SKU-" + item.getSkuId());
                record.put("productName", "未知商品");
            }
            
            records.add(record);
        }
        
        return records;
    }
}




